if not processor then


processor = {timer = 1000, on_run_delay = 10, collect_timer = 10000}

math.randomseed(os.time())


function processor:AddCallback(name)
	if not name then return end
	if not self.priority_table then self.priority_table = {} end
	for i, v in ipairs(self.priority_table) do
		if v == name then return end
	end
	--table.sinsert(self.priority_table, 1, name)
	table.sinsert(self.priority_table, name)
	if not self.data_table then self.data_table = {} end
	self.data_table[name] = {}
end


function processor:AddInit(param1, param2)
	if not self.handlers_table then self.handlers_table = {} end
	if not self.handlers_table.OnInit then self.handlers_table.OnInit = {} end
	if param2 then
		table.sinsert(self.handlers_table.OnInit, param1, param2)
	else
		table.sinsert(self.handlers_table.OnInit, param1)
	end
end


function processor:AddStop(handler)
	if not self.handlers_table then self.handlers_table = {} end
	if not self.handlers_table.OnStop then self.handlers_table.OnStop = {} end
	table.sinsert(self.handlers_table.OnStop, 1, handler)
end


function processor:AddTimer(handler)
	self:AddHandler("OnTimer", handler)
end


function processor:AddHandler(name, handler)
	if not name then return end
	if name == "OnInit" then
		return self:AddInit(handler)
	elseif name == "OnStop" then
		return self:AddStop(handler)
	end
	if not self.handlers_table then self.handlers_table = {} end
	if not self.handlers_table[name] then self.handlers_table[name] = {} end
	--table.sinsert(self.handlers_table[name], 1, handler)
	table.sinsert(self.handlers_table[name], handler)
end


function processor:CallHandlers(name, data, qn)
	if not name then
		for i, v in ipairs(self.priority_table) do
			self:CallHandlers(v)
		end
	elseif data then
		for i, v in ipairs(self.handlers_table[name]) do
			if self.is_run or name == "OnStop" then
				if v(data, name, qn) then return true end
			end
		end
	else
		repeat
			data, qn = self:GetData(name)
			if data then
				if self:CallHandlers(name, data, qn) then break end
				self:DropData(name)
			end
		until not data
	end
end


function processor:PushData(name, data)
	if not name
		or not self.handlers_table
		or not self.handlers_table[name]
		or #self.handlers_table[name] <= 0
	then return end
	table.sinsert(self.data_table[name], data)
end


function processor:GetData(name)
	if not name then return nil end
	--if #self.data_table[name] <= 0 then return end
	
	return self.data_table[name][1], #self.data_table[name]
end


function processor:DropData(name)
	if name and #self.data_table[name] > 0 then
		table.sremove(self.data_table[name], 1)
		self.pop_count = self.pop_count + 1
	end
end


function processor:IsData(name)
	if name and #self.data_table[name] > 0 then return #self.data_table[name] end
end


function processor:SetTimer(t)
	if t >= 100 then self.timer = t end
end


function processor:GetTime(delay)
	return os.clock() + (delay or 0) / 1000.0
end


function processor:IsDelay(time, delay)
	local now = self:GetTime()
	if not time or time <= 0 or time + (delay or 0) / 1000.0 <= now then
		return now
	end
end


function processor:stop(f)
	self:PushData("OnStop", f)
	self.is_run = false
end


function OnInit(path)
	processor.init_path = path
end


function OnStop(f)
	processor:stop(3)
	return 100
end


function main()
	math.randomseed(os.time())
	
	local st = 100
	processor.is_run = true
	
	local t = processor:GetTime()
	if t < 3 then
		processor:PushData("OnRun", t)
	end
	
	processor:PushData("OnInit", processor.init_path)
	
	processor:AddStop(function(data)
		processor.is_run = false
	end)
	
	while processor:GetTime() < processor.on_run_delay do
		sleep(st)
	end
	
	local timer_time = 0
	local date_time = getTradeDate().date
	local timer_collect = 0
	
	repeat
		if not processor:GetData("OnRun") and not processor:GetData("OnInit") then
			t = getTradeDate().date
			if t and date_time ~= t then
				if date_time then
					processor:PushData("OnDate", t)
				end
				date_time = t
			end
			
			if not processor:GetData("OnTimer") then
				t = processor:IsDelay(timer_time, processor.timer)
				if t then
					processor:PushData("OnTimer", t - timer_time)
					timer_time = t
				end
			end
		end
		
		processor.pop_count = 0
		
		processor:CallHandlers()
		
		if processor.collect_timer and processor.collect_timer > 0 then
			t = processor:IsDelay(timer_collect, processor.collect_timer)
			if t then
				timer_collect = t
				
				collectgarbage("collect")
			end
		end
		
		if processor.is_run then
			if st > 0 then
				if processor.pop_count > 0 then
					sleep(st)
				else
					sleep(st * 2)
				end
			end
		else
			break
		end
	until false
	
	processor = nil
end


processor:AddCallback("OnRun")		-- script starts at terminal run
processor:AddCallback("OnInit")
processor:AddCallback("OnStop")
processor:AddCallback("OnDate")		-- trade date changed
processor:AddCallback("OnTimer")


end -- of file
